home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Hacks
/
Hacks ’96
/
ArrangeScript
/
Sources
/
Plugin.cp
< prev
next >
Wrap
Text File
|
1996-06-21
|
14KB
|
436 lines
/*
This file defines a "generic" plugin module for Arrange 2.0.
To use it, you should modify the file 'SubClass.h', which subclasses
the Plugin class definition by adding new fields and private functions,
and implementing the appropriate methods in another C++ source file.
I'd strongly suggest that you base your plugin on one of the examples,
or at least be familiar with one or more of them. You should not have to
examine or make changes to this file or Plugin.h. Most of the code
contained here hides the details of interfacing Arrange and the module
'hook' mechanism to C++
There is also a required 'MDdf' resource, which may be built by including
'Plugin.r' within your own rez source file. Note that the 'MDdf' resource
built by compiling Plugin.r assumes the 'MDcd' code resource has the same
'qModuleRsrcID' ID as the MDdf (the usual convention).
This version of Plugin.cp was written by Paul Chambers on 11/27/94 and
last updated on 12/6/84.
It is derived from the original GenericPlugin.cp, written by
Steve Newman on 12/24/93 and last updated on 7/15/94.
*/
#include "ArrangeCallbacks.h"
#include "PlugIn.h"
#include "ArrangeScript.h"
/*************************************************************************/
/**************************** Main entry point ***************************/
/*************************************************************************/
/* Root entry point for the module - must be the first function in the
* file, so that the linker will place it first in the code segment.
* This is the routine which Arrange calls at application startup time
* (and again at quit time).
*
* Most plug-ins will not need to modify this routine or the Hook functions
* immediately following. All customization can be done in the "Plugin"
* section (below).
*/
extern "C" Integer main(ModuleParamBlock *pb, pModuleRootAction action, Integer /*p1*/ ENDP)
{
ArrangeCallbackTbl* calls;
Integer returnValue;
// A4 doesn't yet point to our data segment, so we cannot use any global data.
SetupGlobals();
/* Extract the callback table from our parameter block, and coerce it
* to the extended Arrange table.
*/
calls = (ArrangeCallbackTbl*)(pb->calls);
switch (action)
{
case mrLoad:
// Allocate memory and create a new Plugin object.
void* storage = calls->mem->AllocMem( sizeof(SubClass),
(AllocMode)(amFreeStore | amErrIfNoMem));
pb->moduleRefcon = uInteger(new(storage) SubClass(calls));
returnValue = 1;
break;
case mrUnload:
// Dispose of the Plugin object and release the memory it occupies.
delete (SubClass *)pb->moduleRefcon;
calls->mem->DeallocMem((void*)pb->moduleRefcon, amFreeStore);
returnValue = 0;
break;
case mrFindEntry:
default:
// This module contains no extended entry points, so we always return 0 for
// the mrFindEntry message. Most plug-ins will not use extended entry points.
returnValue = 0;
break;
} // switch (action)
RestoreGlobals();
return returnValue;
} // OurModuleRoot
// Stubs to resolve the 'new' & 'delete' references.
void* Plugin::operator new(size_t)
{
DebugStr("\pError - naked 'operator new' called.");
return nil;
}
/*************************************************************************\
Class Plugin
\*************************************************************************/
/* Construct a Plugin object. This is called once, from the OurModuleRoot
* function, when the module is initialized (i.e. at application startup time).
*/
Plugin::Plugin(const ArrangeCallbackTbl* theCalls)
{
// Record the callback table for future use.
calls = theCalls;
} // Plugin constructor
/* Dispose of a Plugin object. This is called when Arrange terminates. You
* should free up any data structures which you allocation in the Plugin
* constructor (above).
*/
Plugin::~Plugin()
{
} // ~Plugin
/*
following are a number of groups of routines, which form the bulk
of the interface between the Arrange module API and the subclass.
The 'moduleRefcon' of the 'ModuleParamBlock' is used to maintain a
pointer to the subclass derived from this class. The 'InstallxxxxHook'
routines set up a private 'OurxxxxHook' function, which uses the
'moduleRefcon' field to establish 'this' and invoke the appropriate
'xxxxEvent' method, which should be overridden in the subclass.
The methods provided here are essentially 'do nothing' methods.
*/
/* This function is called whenever the user clicks in an "interesting place"
* in a document window. It should return true if we handle the click, false
* (the normal case) when the click should be passed along to other plug-ins
* or to Arrange's normal event processing. See the documentation for
* SetClickHook for more details.
*/
void Plugin::InstallClickHook ( uInteger refcon, pBoolean addHook )
{ calls->ui->SetClickHook(OurClickHook, refcon, addHook); }
arHookResult OurClickHook( ModuleParamBlock* pb, arClickLocation loc,
Point where, pShort modifiers, pShort clickCount,
arNoteID note, arFieldID field, arPathID path ENDP )
{
arHookResult result;
SetupGlobals();
result = ((SubClass*)(pb->moduleRefcon))->ClickEvent(
loc, where, modifiers, clickCount, note, field, path );
RestoreGlobals();
return result;
}
arHookResult Plugin::ClickEvent( arClickLocation /*loc*/, Point /*where*/,
Short /*modifiers*/, Short /*clickCount*/,
arNoteID /*note*/, arFieldID /*field*/,
arPathID /*path*/ )
{
return false; // Let Arrange handle the event
} // ClickEvent
/* This function is called whenever the user types a key which matches the
* filters we pass to SetKeyHook in Plugin's constructor. It should return
* true if we handle the event, false (the normal case) when the event
* should be passed along to other plug-ins or to Arrange's normal event
* processing. See the documentation for SetKeyHook for more details.
*/
void Plugin::InstallKeyHook ( uInteger refcon, pBoolean addHook,
pShort charFilter, pShort keyFilter, pShort modFilter )
{
calls->ui->SetKeyHook (OurKeyHook, refcon, addHook,
charFilter, keyFilter, modFilter);
}
arHookResult OurKeyHook( ModuleParamBlock* pb, pShort theChar, pShort key,
pShort modifiers ENDP )
{
arHookResult result;
SetupGlobals();
result = ((SubClass*)(pb->moduleRefcon))->KeyEvent(theChar, key, modifiers);
RestoreGlobals();
return result;
}
arHookResult Plugin::KeyEvent(Short /*theChar*/, Short /*key*/, Short /*modifiers*/)
{
return false; // Let Arrange handle the event
} // KeyEvent
/* This function is called whenever the user chooses a menu item for which
* we have registered (via the SetMenuHook function). It should return true
* if we handle the command, false (the normal case) when the command should
* be passed along to other plug-ins or to Arrange's normal event processing.
* See the documentation for SetMenuHook for more details.
*/
void Plugin::InstallMenuHook ( uInteger refcon, pBoolean addHook, Integer commandCode )
{
calls->ui->SetMenuHook (OurMenuHook, refcon, addHook, commandCode);
}
arHookResult OurMenuHook( ModuleParamBlock* pb, Integer commandCode,
Integer commandParam, pShort modifiers ENDP )
{
arHookResult result;
SetupGlobals();
result = ((SubClass*)(pb->moduleRefcon))->MenuEvent(
commandCode, commandParam, modifiers );
RestoreGlobals();
return result;
}
arHookResult Plugin::MenuEvent( Integer /*commandCode*/, Integer /*commandParam*/,
Short /*modifiers*/ )
{
return false; // Let Arrange handle the event
} // MenuEvent
/* If we register to recieve events for a field by calling SetFieldHook, this
* function will be called for any events in that field. It should return
* false in almost all cases. See the documentation for SetFieldHook for
* more details.
*/
void Plugin::InstallFieldHook ( uInteger refcon, pBoolean addHook, arFieldID field )
{
calls->ui->SetFieldHook(OurFieldHook, refcon, addHook, field);
}
void Plugin::RegisterFieldProc (const char* name, Integer id, arFPType type,
Integer fieldTypes, uInteger refcon ENDP )
{
calls->ui->RegisterFieldProc( name, id, type, fieldTypes, OurFieldHook, refcon );
}
arHookResult OurFieldHook( ModuleParamBlock* pb, arNoteID note,
arFieldID field, arFieldAction action,
const char* choiceText ENDP )
{
arHookResult result;
SetupGlobals();
result = ((SubClass*)(pb->moduleRefcon))->FieldEvent(
note, field, action,choiceText );
RestoreGlobals();
return result;
}
arHookResult Plugin::FieldEvent( arNoteID /*note*/, arFieldID /*field*/,
arFieldAction /*action*/, const char* /*choiceText*/ )
{
return false;
} // FieldEvent
/* This function is called whenever the user switches windows or changes
the current folder/topic/view in the front window. See the documentation
for SetTopicHook for more details.
*/
void Plugin::InstallTopicHook ( uInteger refcon, pBoolean addHook )
{
calls->ui->SetTopicHook(OurTopicHook, refcon, addHook);
}
void OurTopicHook( ModuleParamBlock* pb, arTopicID newTopic,
arWindowID newWindow, arTopicAction action ENDP )
{
SetupGlobals();
((SubClass*)(pb->moduleRefcon))->TopicEvent(newTopic, newWindow, action);
RestoreGlobals();
}
void Plugin::TopicEvent( arTopicID /*newTopic*/, arWindowID /*newWindow*/,
arTopicAction /*action*/ )
{
} // TopicEvent
/* This function is called periodically, whenever Arrange recieves a null
event from the Event Manager.
*/
void Plugin::InstallTickHook( uInteger refcon, pBoolean addHook )
{
calls->ui->SetTickHook (OurTickHook, refcon, addHook);
}
void OurTickHook(ModuleParamBlock* pb ENDP)
{
SetupGlobals();
((SubClass*)(pb->moduleRefcon))->TickEvent();
RestoreGlobals();
}
void Plugin::TickEvent()
{
} // TickEvent
/* This function is called whenever various file-level events occur. It
* should return true in almost all cases. See the documentation for
* SetFileHook for more details.
*/
void Plugin::InstallFileHook ( uInteger refcon, pBoolean addHook )
{
calls->ui->SetFileHook (OurFileHook, refcon, addHook);
}
arHookResult OurFileHook(ModuleParamBlock* pb, arFileAction action ENDP)
{
arHookResult result;
SetupGlobals();
result = ((SubClass*)(pb->moduleRefcon))->FileEvent(action);
RestoreGlobals();
return result;
}
arHookResult Plugin::FileEvent(arFileAction /*action*/)
{
return true;
} // FileEvent
/* This function is called if the user voluntarily quits Arrange. It should
* return true to allow the user to quit, false to prevent it. See the
* documentation for SetQuitHook for more details.
*/
void Plugin::InstallQuitHook( uInteger refcon, pBoolean addHook )
{
calls->ui->SetQuitHook(OurQuitHook, refcon, addHook);
}
arHookResult OurQuitHook(ModuleParamBlock* pb ENDP)
{
arHookResult result;
SetupGlobals();
result = ((SubClass*)(pb->moduleRefcon))->QuitEvent();
RestoreGlobals();
return result;
}
arHookResult Plugin::QuitEvent()
{
return true;
} // QuitEvent
/* This function is called whenever the user clicks in the menu bar or types
* a command key, just before processing the event. It should do any fixing
* up of menus which might be necessary based on the current state of affairs.
* See the documentation for SetATMHook for more details.
*/
void Plugin::InstallATMHook( uInteger refcon, pBoolean addHook )
{
calls->ui->SetATMHook(OurATMHook, refcon, addHook);
}
void OurATMHook(ModuleParamBlock* pb ENDP)
{
SetupGlobals();
((SubClass*)(pb->moduleRefcon))->ATMEvent();
RestoreGlobals();
}
void Plugin::ATMEvent()
{
} // ATMEvent
/***********************************************************************/
/*
This function is called whenever the user imports a file of a type
for which this plugin registered a format. It is called first to
assess how likely it is that the provided format is the import
format supported, and then again to import the format.
*/
void Plugin::RegisterImportFormat( const char* name, Integer formatID,
OSType* fileTypes, Integer fileTypeCount,
uInteger refcon ENDP )
{
calls->ui->RegisterImportFormat( name, formatID, fileTypes, fileTypeCount,
OurImportHook, refcon );
}
Integer OurImportHook( ModuleParamBlock* pb, const FSSpec *file,
pShort fRefnum, Integer formatID,
pBoolean sniff, arTopicID destTopic ENDP )
{
Integer result;
SetupGlobals();
result = ((SubClass*)(pb->moduleRefcon))->ImportFile( file, fRefnum, formatID,
sniff, destTopic );
RestoreGlobals();
return result;
}
Integer Plugin::ImportFile( const FSSpec* /*file*/, pShort /*fRefnum*/,
Integer /*formatID*/, pBoolean /*sniff*/, arTopicID /*destTopic*/ )
{
return 0;
}
/*
Export the provided topic to the given file. Assume that the file is already
open, and leave the file open and unflushed.
*/
void Plugin::RegisterExportFormat ( const char* name, Integer formatID, arEFType type,
uInteger refcon, OSType fileType, OSType fileCreator ENDP )
{
calls->ui->RegisterExportFormat( name, formatID, type,
OurExportHook, refcon, fileType, fileCreator );
}
Integer OurExportHook( ModuleParamBlock* pb, const FSSpec *file,
pShort fRefnum, Integer formatID,
arEFType type, arTopicID srcTopic ENDP )
{
Integer result;
SetupGlobals();
result = ((SubClass*)(pb->moduleRefcon))->ExportTopic(file, fRefnum, formatID, type, srcTopic);
RestoreGlobals();
return result;
}
Integer Plugin::ExportTopic(const FSSpec* /*file*/,
pShort /*fRefnum*/, Integer /*formatID*/,
arEFType /*type*/, arTopicID /*srcTopic*/)
{
return 0;
}
/**************************************************************************************/